using System.Collections;

namespace Crux.Core.Websockets;
/// <summary>
/// WebSocketConnectionStore
/// </summary>
public class WebSocketConnectionStore
    : IDisposableObservable
{
    /// <summary>
    ///
    /// </summary>
    public int Count => pool.Count;
    /// <summary>
    ///
    /// </summary>
    public bool IsDisposed { get; private set; }

    /// <summary>
    ///
    /// </summary>
    private readonly ConcurrentDictionary<string, WebSocketConnectionContext> pool = new ConcurrentDictionary<string, WebSocketConnectionContext>();

    /// <summary>
    ///
    /// </summary>
    public WebSocketConnectionStore(CancellationToken cancellationToken = default)
    {
        cancellationToken.Register(() => this.Dispose());
    }

    /// <summary>
    ///
    /// </summary>
    public WebSocketConnectionContext? this[string connectionId]
    {
        get
        {
            if (pool.TryGetValue(connectionId, out var context))
                return context;

            return default;
        }
    }

    /// <summary>
    ///
    /// </summary>
    public void Dispose()
    {
        if (this.IsDisposed) return;

        this.IsDisposed = true;
        this.pool.Clear();
        GC.SuppressFinalize(this);
    }

    /// <summary>
    ///
    /// </summary>
    public bool Add(WebSocketConnectionContext context) => pool.TryAdd(context.ConnectionId, context);

    /// <summary>
    ///
    /// </summary>
    public bool Remove(WebSocketConnectionContext context) => pool.TryRemove(context.ConnectionId, out _);

    /// <summary>
    ///
    /// </summary>
    public Enumerator GetEnumerator() => new Enumerator(this);

    /// <summary>
    ///
    /// </summary>
    public readonly struct Enumerator : IEnumerator<WebSocketConnectionContext>
    {
        /// <summary>
        ///
        /// </summary>
        private readonly IEnumerator<KeyValuePair<string, WebSocketConnectionContext>> _enumerator;

        /// <summary>
        ///
        /// </summary>
        public Enumerator(WebSocketConnectionStore webSocketConnectionStore)
        {
            this._enumerator = webSocketConnectionStore.pool.GetEnumerator();
        }

        /// <summary>
        ///
        /// </summary>
        public WebSocketConnectionContext Current => _enumerator.Current.Value;

        object IEnumerator.Current => this.Current;

        #region IEnumerator methods implement
        /// <summary>
        ///
        /// </summary>
        public bool MoveNext() => _enumerator.MoveNext();
        /// <summary>
        ///
        /// </summary>
        public void Reset() => _enumerator.Reset();
        /// <summary>
        ///
        /// </summary>
        public void Dispose() => _enumerator.Dispose();
        #endregion
    }
}
